﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using BaMusaSoft.RPS.RPSServices.Reports;

namespace BaMusaSoft.RPS.ViewModel.Infrastructure
{
    public class AllSchedulesSearchFields:INotifyPropertyChanged
    {
        #region
        string _scheduleId;
        string _propertyNo;
        string _fromDate;
        string _toDate;
        #endregion
        public string ScheduleId
        {
            get { return _scheduleId; }
            set
            {
                if (_scheduleId != value)
                {
                    _scheduleId = value;
                    RaisePropertyChanged("ScheduleId");
                }
            }
        }
        public string PropertyNo
        {
            get { return _propertyNo; }
            set
            {
                if (_propertyNo != value)
                {
                    _propertyNo = value;
                    RaisePropertyChanged("PropertyNo");
                }
            }
        }
        public string FromDate
        {
            get { return _fromDate; }
            set
            {
                if (_fromDate != value)
                {
                    _fromDate = value;
                    RaisePropertyChanged("FromDate");

                }
            }
        }
        public string ToDate
        {
            get { return _toDate; }
            set
            {
                if (_toDate != value)
                {
                    _toDate = value;
                    RaisePropertyChanged("ToDate");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }

        }
        /// <summary>
        /// Build criteria based on current instance search properties values.
        /// </summary>
        /// <returns>The Expression built. Null of not any of the proeprties has value.</returns>
        public Expression<Func<AllSchedulesReportFields, bool>> BuildCriteria()
        {
            MethodInfo stringNullOrEmpty = typeof(string).GetMethod("IsNullOrEmpty");
            MethodInfo contains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
            MethodInfo compareTo = typeof(string).GetMethod("CompareTo", new[] { typeof(string) });
            MethodInfo startsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
            ParameterExpression param = Expression.Parameter(typeof(AllSchedulesReportFields), "allSchedules");
            Expression expr = null;

            Expression scheduleIdProperty = Expression.PropertyOrField(param, "ScheduleId");
            Expression propertyNoPropery = Expression.PropertyOrField(param, "PropertyNo");
            Expression fromDateProperty = Expression.PropertyOrField(param, "DateDue");
            Expression toDateProperty = Expression.PropertyOrField(param, "DateDue");

            Expression scheduleIdValue = ConstantExpression.Constant(this.ScheduleId, typeof(string));
            Expression propertyNoValue = ConstantExpression.Constant(this.PropertyNo, typeof(string));
            Expression fromDateValue = ConstantExpression.Constant(this.FromDate, typeof(string));
            Expression toDateValue = ConstantExpression.Constant(this.ToDate, typeof(string));


            bool expressionAssigned = false;
            if (!string.IsNullOrEmpty(ScheduleId))
            {
                Expression temp = Expression.Call(scheduleIdProperty, startsWith, scheduleIdValue);
                expr = temp;
                if (!expressionAssigned) expressionAssigned = true;
            }
            if (!string.IsNullOrEmpty(PropertyNo))
            {
                if (!expressionAssigned)
                {
                    Expression temp = Expression.Call(propertyNoPropery, startsWith, propertyNoValue);
                    expr = temp;
                    expressionAssigned = true;
                }
                else
                {
                    Expression temp = Expression.Call(propertyNoPropery, startsWith, propertyNoValue);

                    expr = Expression.AndAlso(expr, temp);
                }
            }
            if (!string.IsNullOrEmpty(FromDate))
            {

                if (!expressionAssigned)
                {
                    ConstantExpression constant = Expression.Constant(0);
                    Expression temp = Expression.GreaterThanOrEqual(
                        Expression.Call(fromDateProperty, compareTo, fromDateValue), constant);
                    expr = temp;
                    expressionAssigned = true;
                }
                else
                {
                    ConstantExpression constant = Expression.Constant(0);
                    Expression temp = Expression.GreaterThanOrEqual(
                        Expression.Call(fromDateProperty, compareTo, fromDateValue), constant);
                    expr = Expression.AndAlso(expr, temp);
                }
            }
            if (!string.IsNullOrEmpty(ToDate))
            {
                if (!expressionAssigned)
                {
                    ConstantExpression constant = Expression.Constant(0);
                    Expression temp = Expression.LessThanOrEqual(
                        Expression.Call(toDateProperty, compareTo, toDateValue), constant);
                    expr = temp;
                    expressionAssigned = true;
                }
                else
                {
                    ConstantExpression constant = Expression.Constant(0);
                    Expression temp = Expression.LessThanOrEqual(
                        Expression.Call(toDateProperty, compareTo, toDateValue), constant);
                    expr = Expression.AndAlso(expr, temp);
                }
            }
            Expression<Func<AllSchedulesReportFields, bool>> criteria = null;
            if (expr != null)
            {
                criteria = Expression.Lambda<Func<AllSchedulesReportFields, bool>>(expr, param);
            }
            return criteria;
        }
    }
}
